using System;
using System.Collections.Generic;
using System.Linq;
using Isis.Interfaces;

namespace Isis
{
    public class ControllerRepository : IControllerRepository
    {
        private const string BASE_ISIS_CONTROLPANEL_URL = "/isis";

        public IControlPanelController GetControllerByName(string name)
        {
            IEnumerable<Type> allControllers = GetAllControllerTypes();
            Type type = allControllers.SingleOrDefault(c => SelectByName(c, name));
            if (type != null)
            {
                return (IControlPanelController)Activator.CreateInstance(type, BASE_ISIS_CONTROLPANEL_URL);
            }
            return null;
        }

        public IEnumerable<string> GetControllerTabNames()
        {
            IEnumerable<IControlPanelController> controlPanelControllers = GetAllControllers();

            return controlPanelControllers.OrderBy(x => x.Tab.DisplayPriority).Select(c => c.Tab.Title);
        }

        public IEnumerable<string> GetControllerSubTabNames(string tabName)
        {
            IControlPanelController controlPanelController = GetAllControllers().Single(x => x.Tab.Title == tabName);
            return controlPanelController.SubTabs;
        }

        private bool SelectByName(Type c, string name)
        {
            return string.Compare(GetControllerNameFromType(c), name, true) == 0;
        }

        public string GetControllerNameFromType(Type c)
        {
            int removePoint = c.Name.LastIndexOf("Controller");
            return c.Name.Substring(0, removePoint);
        }

        public static IEnumerable<IControlPanelController> GetAllControllers()
        {
            foreach (Type controllerType in GetAllControllerTypes())
            {
                var controller = (IControlPanelController) Activator.CreateInstance(controllerType, BASE_ISIS_CONTROLPANEL_URL);
                if (controller.Tab != null)
                {
                    yield return controller;
                }
            }
        }

        public static IEnumerable<Type> GetAllControllerTypes()
        {
            return AppDomain
            .CurrentDomain
            .GetAssemblies()
            .SelectMany(assembly => assembly.GetTypes())
            .Where(type => 
                typeof (IControlPanelController).IsAssignableFrom(type) 
                && !type.IsAbstract 
                && !type.IsInterface
                );
        }
    }
}